-
-
Notifications
You must be signed in to change notification settings - Fork 109
Add preact-ui package #219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughThis PR adds a new Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ChatInput
participant ChatContext as Chat
participant Backend
participant ChatMessages
participant ChatMessage
User->>ChatInput: Enter text & submit
ChatInput->>ChatContext: sendMessage(userMessage)
ChatContext->>Backend: send request / stream
Backend-->>ChatContext: stream response chunks
ChatContext->>ChatMessages: update messages state
ChatMessages->>ChatMessage: render new message(s)
ChatMessage->>ChatMessage: render parts (Text/Thinking/Tool)
ChatMessages-->>User: updated conversation UI
sequenceDiagram
participant ChatMessage
participant TextPart
participant ThinkingPart
participant ToolApproval
participant CustomRenderer as Custom Renderer
ChatMessage->>ChatMessage: iterate message.parts
alt part.type == "text"
ChatMessage->>CustomRenderer: call textPartRenderer?
alt custom renderer provided
CustomRenderer-->>ChatMessage: rendered node
else
ChatMessage->>TextPart: render Markdown
TextPart-->>ChatMessage: rendered node
end
else part.type == "thinking"
ChatMessage->>ThinkingPart: render collapsible thinking block
ThinkingPart-->>ChatMessage: rendered node
else part.type == "tool-call"
ChatMessage->>ToolApproval: render approval UI if needed
ToolApproval-->>ChatMessage: approval outcome/UI
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
c38230f to
12d68b5
Compare
|
View your CI Pipeline Execution ↗ for commit ef0d14f
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-anthropic
@tanstack/ai-client
@tanstack/ai-devtools-core
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-preact
@tanstack/ai-preact-ui
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
|
Fixing plugin types in JoviDeCroock/preact-markdown#2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@packages/typescript/ai-preact-ui/README.md`:
- Around line 8-16: The badges in README.md point to `@tanstack/ai` instead of
this package; update the npm and bundlephobia badge links and image sources to
reference `@tanstack/ai-preact-ui` (replace occurrences of "@tanstack/ai" with
"@tanstack/ai-preact-ui" in the first and third <a> blocks), leaving the GitHub
stars badge as-is if it should still target the repo; ensure href and the src
badge URLs both use the corrected package name so badges show the right metrics.
- Line 2: The README references a missing image and lacks alt text; add the
image file at packages/typescript/ai-preact-ui/media/header_ai.png and update
the README's <img src="./media/header_ai.png"> tag to include descriptive alt
text (e.g., alt="AI Preact UI header") so the file exists and the image tag
includes accessibility text.
In `@packages/typescript/ai-preact-ui/src/chat.tsx`:
- Line 52: ChatProps declares a tools?: Record<string, any> prop that the Chat
component doesn't destructure or forward to useChat, leaving dead code; either
remove the tools field from ChatProps and any related types/usages, or
destructure tools in the Chat component (e.g. function Chat({..., tools}:
ChatProps)) and pass it into useChat (e.g. useChat({ ..., tools })) so the prop
is consumed—update tests/types accordingly and ensure any runtime behavior
expecting tools is preserved.
In `@packages/typescript/ai-preact-ui/src/text-part.tsx`:
- Around line 65-71: The implementation currently sets roleClassName to '' for
system messages causing a mismatch with the JSDoc; change the conditional that
computes roleClassName (the role === 'user' ? userClassName : role ===
'assistant' ? assistantClassName : '') so that the fallback for the 'system'
role uses assistantClassName (i.e., treat role === 'system' same as
'assistant'), or if the intended behavior is to keep an empty class for system,
update the JSDoc that describes assistantClassName to remove the "also used for
system messages" claim; adjust either the roleClassName logic or the JSDoc
accordingly so they match.
🧹 Nitpick comments (8)
packages/typescript/ai-preact-ui/README.md (1)
12-25: Replace hard tabs with spaces.Static analysis flagged hard tabs on lines 12 and 23-25. Consider using spaces for consistent formatting.
packages/typescript/ai-preact-ui/vite.config.ts (1)
10-12: Consider usingjsdomorhappy-domenvironment for UI component tests.This Preact UI component library currently has no tests, but when you add component tests that render or interact with the DOM, you'll need a DOM-emulating environment like
jsdomorhappy-dominstead of'node'.Proposed change when tests are added
globals: true, - environment: 'node', + environment: 'jsdom', include: ['tests/**/*.test.ts'],packages/typescript/ai-preact-ui/src/chat-messages.tsx (1)
53-66: Consider handling error state even whenerrorStateis not provided.When an error occurs but no
errorStaterenderer is provided, the component silently falls through to render messages (or empty/loading states). This could be confusing if errors go unnoticed.Consider either:
- Rendering a default error UI when
errorexists buterrorStateis undefined- Documenting this as expected behavior (error ignored unless errorState provided)
packages/typescript/ai-preact-ui/src/chat-message.tsx (3)
5-12: Consider stronger typing forapprovalandoutput.Using
anyfor these fields loses type safety benefits. If the shape is known from@tanstack/ai-clientor@tanstack/ai-preact, consider importing and using those types.Example improvement
export interface ToolCallRenderProps { id: string name: string arguments: string state: string - approval?: any - output?: any + approval?: { approved?: boolean } // or import from `@tanstack/ai-client` + output?: unknown }
198-201: Redundant optional chaining.After the truthy check on line 199, the optional chaining on line 200 is unnecessary.
Suggested fix
// Check if there's a specific renderer for this tool if (toolsRenderer?.[part.name]) { - return <>{toolsRenderer[part.name]?.(toolProps)}</> + return <>{toolsRenderer[part.name](toolProps)}</> }
149-157: Typepartmore specifically to improve type safety.Using
anyforpartloses the benefit of type narrowing in the conditional blocks. Consider importing theMessageParttype from@tanstack/ai-client.Suggested improvement
+import type { MessagePart } from '@tanstack/ai-client' import type { UIMessage } from '@tanstack/ai-preact' function MessagePart({ part, // ... }: { - part: any + part: MessagePart // ... })packages/typescript/ai-preact-ui/src/tool-approval.tsx (1)
53-54: Clarify whytoolCallIdis accepted but ignored.The
toolCallIdprop is destructured and explicitly assigned to_, indicating it's intentionally unused. However, this may confuse consumers who expect it to be used. Consider either:
- Removing it from props if it's not needed
- Adding a comment explaining why it's accepted but not used (e.g., for API consistency)
- Using it for the approval response if that's the intended behavior
export function ToolApproval({ - toolCallId: _, + // toolCallId is accepted for API consistency but approval.id is used for responses + toolCallId: _toolCallId, toolName,packages/typescript/ai-preact-ui/src/chat-input.tsx (1)
104-117: Consider renamingdata-chat-textareaattribute.The attribute
data-chat-textareais applied to an<input>element, which is misleading. Consider renaming todata-chat-inputfor consistency.placeholder={placeholder} disabled={disabled} - data-chat-textarea + data-chat-input style={{
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
packages/typescript/ai-preact-ui/CHANGELOG.mdpackages/typescript/ai-preact-ui/README.mdpackages/typescript/ai-preact-ui/package.jsonpackages/typescript/ai-preact-ui/src/chat-input.tsxpackages/typescript/ai-preact-ui/src/chat-message.tsxpackages/typescript/ai-preact-ui/src/chat-messages.tsxpackages/typescript/ai-preact-ui/src/chat.tsxpackages/typescript/ai-preact-ui/src/index.tspackages/typescript/ai-preact-ui/src/text-part.tsxpackages/typescript/ai-preact-ui/src/thinking-part.tsxpackages/typescript/ai-preact-ui/src/tool-approval.tsxpackages/typescript/ai-preact-ui/tsconfig.jsonpackages/typescript/ai-preact-ui/vite.config.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from/adapterssubpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions withtoolDefinition()and Zod schema inference
Implement isomorphic tool system usingtoolDefinition()with.server()and.client()implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Files:
packages/typescript/ai-preact-ui/src/text-part.tsxpackages/typescript/ai-preact-ui/src/thinking-part.tsxpackages/typescript/ai-preact-ui/src/chat-message.tsxpackages/typescript/ai-preact-ui/src/chat-messages.tsxpackages/typescript/ai-preact-ui/src/tool-approval.tsxpackages/typescript/ai-preact-ui/src/chat-input.tsxpackages/typescript/ai-preact-ui/src/index.tspackages/typescript/ai-preact-ui/src/chat.tsxpackages/typescript/ai-preact-ui/vite.config.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for function and variable names throughout the codebase
Files:
packages/typescript/ai-preact-ui/src/text-part.tsxpackages/typescript/ai-preact-ui/src/thinking-part.tsxpackages/typescript/ai-preact-ui/src/chat-message.tsxpackages/typescript/ai-preact-ui/src/chat-messages.tsxpackages/typescript/ai-preact-ui/src/tool-approval.tsxpackages/typescript/ai-preact-ui/src/chat-input.tsxpackages/typescript/ai-preact-ui/src/index.tspackages/typescript/ai-preact-ui/src/chat.tsxpackages/typescript/ai-preact-ui/vite.config.ts
packages/typescript/*/src/index.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Export tree-shakeable adapters with clear subpath exports in package.json (e.g.,
@tanstack/ai/adapters,@tanstack/ai-openai/adapters) to minimize bundle size
Files:
packages/typescript/ai-preact-ui/src/index.ts
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Applied to files:
packages/typescript/ai-preact-ui/README.mdpackages/typescript/ai-preact-ui/tsconfig.jsonpackages/typescript/ai-preact-ui/CHANGELOG.mdpackages/typescript/ai-preact-ui/package.jsonpackages/typescript/ai-preact-ui/src/index.tspackages/typescript/ai-preact-ui/vite.config.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Applied to files:
packages/typescript/ai-preact-ui/README.mdpackages/typescript/ai-preact-ui/CHANGELOG.mdpackages/typescript/ai-preact-ui/package.jsonpackages/typescript/ai-preact-ui/src/index.tspackages/typescript/ai-preact-ui/src/chat.tsx
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Applied to files:
packages/typescript/ai-preact-ui/tsconfig.jsonpackages/typescript/ai-preact-ui/src/index.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/model-meta.ts : Maintain model metadata files that define provider options and capabilities per model for per-model type safety
Applied to files:
packages/typescript/ai-preact-ui/tsconfig.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Applied to files:
packages/typescript/ai-preact-ui/tsconfig.jsonpackages/typescript/ai-preact-ui/src/index.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference
Applied to files:
packages/typescript/ai-preact-ui/tsconfig.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to .prettierrc* : Use Prettier for code formatting with project-configured rules
Applied to files:
packages/typescript/ai-preact-ui/tsconfig.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to .eslintrc* : Use ESLint with custom TanStack config for linting all TypeScript and JavaScript files
Applied to files:
packages/typescript/ai-preact-ui/tsconfig.jsonpackages/typescript/ai-preact-ui/vite.config.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement isomorphic tool system using `toolDefinition()` with `.server()` and `.client()` implementations for dual-environment execution
Applied to files:
packages/typescript/ai-preact-ui/src/tool-approval.tsx
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/*/package.json : Use `workspace:*` protocol for internal package dependencies in package.json (e.g., `"tanstack/ai": "workspace:*"`)
Applied to files:
packages/typescript/ai-preact-ui/package.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.test.ts : Write unit tests using Vitest alongside source files with `.test.ts` naming convention
Applied to files:
packages/typescript/ai-preact-ui/vite.config.ts
🧬 Code graph analysis (6)
packages/typescript/ai-preact-ui/src/text-part.tsx (1)
packages/typescript/ai-preact-ui/src/index.ts (3)
TextPartProps(45-45)TextPart(45-45)TextPart(57-57)
packages/typescript/ai-preact-ui/src/thinking-part.tsx (2)
packages/typescript/ai-preact-ui/src/index.ts (2)
ThinkingPartProps(46-46)ThinkingPart(46-46)examples/vanilla-chat/src/main.js (1)
div(160-160)
packages/typescript/ai-preact-ui/src/chat-message.tsx (1)
packages/typescript/ai-preact-ui/src/thinking-part.tsx (1)
ThinkingPart(44-83)
packages/typescript/ai-preact-ui/src/tool-approval.tsx (1)
packages/typescript/ai-preact-ui/src/chat.tsx (1)
useChatContext(20-28)
packages/typescript/ai-preact-ui/src/chat-input.tsx (2)
packages/typescript/ai-preact-ui/src/index.ts (4)
ChatInputRenderProps(38-38)ChatInputProps(37-37)ChatInput(36-36)useChatContext(28-28)packages/typescript/ai-preact-ui/src/chat.tsx (1)
useChatContext(20-28)
packages/typescript/ai-preact-ui/src/chat.tsx (2)
packages/typescript/ai-preact-ui/src/index.ts (7)
UseChatReturn(61-61)useChatContext(28-28)ChatProps(28-28)ConnectionAdapter(58-58)UIMessage(53-53)Chat(28-28)useChat(49-49)examples/vanilla-chat/src/main.js (2)
message(34-34)div(160-160)
🪛 LanguageTool
packages/typescript/ai-preact-ui/README.md
[style] ~206-~206: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... rounded" /> ``` ### <ToolApproval> Renders approve/deny buttons for tools that req...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 markdownlint-cli2 (0.18.1)
packages/typescript/ai-preact-ui/README.md
2-2: Images should have alternate text (alt text)
(MD045, no-alt-text)
12-12: Hard tabs
Column: 1
(MD010, no-hard-tabs)
23-23: Hard tabs
Column: 1
(MD010, no-hard-tabs)
24-24: Hard tabs
Column: 1
(MD010, no-hard-tabs)
25-25: Hard tabs
Column: 1
(MD010, no-hard-tabs)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Test
- GitHub Check: Preview
🔇 Additional comments (24)
packages/typescript/ai-preact-ui/CHANGELOG.md (1)
1-1: LGTM!Standard initial changelog header for a new package.
packages/typescript/ai-preact-ui/README.md (1)
36-306: Documentation content looks good.The README provides comprehensive documentation covering features, installation, quick start, component APIs, hooks, styling with data attributes, and advanced usage patterns. The examples are clear and demonstrate the intended usage of the headless components well.
packages/typescript/ai-preact-ui/tsconfig.json (1)
1-15: LGTM!The TypeScript configuration is well-structured for a Preact library:
- Correct JSX configuration with
react-jsxandjsxImportSource: "preact"for the new JSX transform- Proper declaration and declarationMap generation for type definitions
- Composite mode enabled for monorepo project references
packages/typescript/ai-preact-ui/vite.config.ts (1)
1-36: Configuration structure looks good.The Vite/Vitest configuration properly integrates with the TanStack build tooling, uses the package name for test identification, and configures appropriate coverage settings.
packages/typescript/ai-preact-ui/package.json (3)
1-56: Package structure follows TanStack conventions.The package manifest correctly uses:
workspace:*protocol for internal dependencies (per coding guidelines)- ESM-only exports matching the Vite config (
cjs: false)- Proper repository metadata and keywords
- Standard script names for the monorepo build system
37-47: No changes needed—this pattern is consistent across framework UI packages in the monorepo.The dual listing of
@tanstack/ai-preactin bothdependenciesandpeerDependenciesmatches the pattern used in other framework UI packages (ai-react-ui,ai-solid-ui, etc.), indicating this is an intentional design choice to provide a fallback while allowing consumers to supply their own version.
39-42: Dependencies are compatible with each other and the unified ecosystem. Bothpreact-md(which depends onunified ^11.0.5) andremark-gfm(which depends onunified ^11.0.0) resolve to[email protected]correctly. Therehype-*plugins do not depend onunifiedand work with the hast AST. No compatibility issues found.packages/typescript/ai-preact-ui/src/thinking-part.tsx (1)
44-83: LGTM! Well-structured collapsible component with good accessibility.The component correctly implements auto-collapse behavior via
useEffect, includes properaria-expandedandaria-labelattributes for accessibility, and the conditional rendering pattern is idiomatic.packages/typescript/ai-preact-ui/src/text-part.tsx (1)
73-83: Good markdown rendering setup.The combination of
rehype-rawfor HTML support,rehype-highlightfor syntax highlighting, andremark-gfmfor GitHub Flavored Markdown provides a comprehensive rendering solution. Per the PR description,preact-mdincludes sanitization.packages/typescript/ai-preact-ui/src/index.ts (1)
1-61: Well-organized barrel exports with clear structure.The exports are logically grouped (components, hooks, types) and the aliasing of
TextPart as TextPartTypecorrectly avoids naming collision with the component export. The re-exports from@tanstack/ai-preactand@tanstack/ai-clientprovide good DX for consumers. Based on learnings, tree-shakeable adapter patterns apply to provider implementations rather than UI component packages, so this barrel approach is appropriate here.packages/typescript/ai-preact-ui/src/chat-messages.tsx (2)
46-51: Auto-scroll implementation is correct.The effect properly triggers on
messageschanges and the immediate scroll (vs smooth) is appropriate for streaming chat scenarios where frequent updates occur.
68-85: Clean message rendering with proper keys.Using
message.idas the key ensures stable DOM reconciliation. The fallback to defaultChatMessagewhen no custom renderer is provided is a good ergonomic choice.packages/typescript/ai-preact-ui/src/chat-message.tsx (1)
94-139: Well-designed component with flexible rendering options.The ChatMessage component provides a good balance of defaults and customization through the various renderer props. The
isThinkingCompletecalculation correctly determines if subsequent text exists, and the part iteration with proper key generation works well.packages/typescript/ai-preact-ui/src/chat.tsx (3)
1-9: LGTM!Clean imports with proper separation of runtime imports and type imports. Good use of the
@tanstack/ai-preactpackage for the headless state management, following the framework integration pattern.
11-28: LGTM!Well-implemented context pattern with appropriate error handling. The error message clearly guides developers on correct usage.
66-96: LGTM!The Chat component correctly composes
useChatwith the provided props and wraps children in a context provider. Thedata-chat-rootattribute enables styling/testing hooks.packages/typescript/ai-preact-ui/src/tool-approval.tsx (3)
1-3: LGTM!Clean imports with proper type separation.
63-75: LGTM!The approval handlers correctly use
approval.idto dispatch responses viaaddToolApprovalResponse. ThehasRespondedderivation correctly handles bothtrueandfalseapproval states.
88-128: LGTM!Well-structured rendering logic with:
- Render prop pattern taking precedence
- Clear status display after response
- Informative pending state with tool name and serialized input
- Semantic data attributes for styling/testing
packages/typescript/ai-preact-ui/src/chat-input.tsx (5)
1-3: LGTM!Clean imports with proper type separation.
5-31: LGTM!Well-defined interfaces with clear JSDoc comments. The render prop pattern provides good flexibility for custom implementations.
59-76: LGTM!Solid implementation with proper state management. The
handleSubmitcorrectly validates input and disabled state before sending.
109-113: Shift+Enter behavior documented but not implemented.The comment at line 29 and JSDoc at line 38 mention "Shift+Enter for new line", but the
onKeyDownhandler doesn't check for the Shift key. Since this is an<input>(not textarea), multi-line isn't possible anyway, but if you intend to support it in the future, the handler should be updated.If Shift+Enter support is intended, consider:
onKeyDown={(e) => { - if (submitOnEnter && e.key === 'Enter') { + if (submitOnEnter && e.key === 'Enter' && !e.shiftKey) { e.preventDefault() handleSubmit() } }}
138-169: LGTM!The submit button correctly handles disabled states and provides visual feedback via hover effects. Loading state is clearly communicated to users.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| @@ -0,0 +1,306 @@ | |||
| <div align="center"> | |||
| <img src="./media/header_ai.png" > | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if the media file exists
echo "=== Checking for media file ==="
fd -t f 'header_ai.png' packages/typescript/ai-preact-ui/ 2>&1 || echo "File not found"
# Also check directory structure
echo -e "\n=== Directory structure ==="
ls -la packages/typescript/ai-preact-ui/media/ 2>&1 || echo "Media directory not found"
# Verify the README.md content at line 2
echo -e "\n=== README.md content around line 2 ==="
sed -n '1,5p' packages/typescript/ai-preact-ui/README.md 2>&1Repository: TanStack/ai
Length of output: 342
Image file is missing and alt text is not provided.
The image file ./media/header_ai.png does not exist in the repository, which breaks the documentation rendering. Additionally, the image tag is missing alt text for accessibility.
Proposed fix
- Add the missing header image file to
packages/typescript/ai-preact-ui/media/header_ai.png - Update the image tag to include alt text:
- <img src="./media/header_ai.png" >
+ <img src="./media/header_ai.png" alt="TanStack AI Preact UI" >📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <img src="./media/header_ai.png" > | |
| <img src="./media/header_ai.png" alt="TanStack AI Preact UI" > |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
2-2: Images should have alternate text (alt text)
(MD045, no-alt-text)
🤖 Prompt for AI Agents
In `@packages/typescript/ai-preact-ui/README.md` at line 2, The README references
a missing image and lacks alt text; add the image file at
packages/typescript/ai-preact-ui/media/header_ai.png and update the README's
<img src="./media/header_ai.png"> tag to include descriptive alt text (e.g.,
alt="AI Preact UI header") so the file exists and the image tag includes
accessibility text.
| * Features: | ||
| * - Auto-growing textarea | ||
| * - Submit on Enter (Shift+Enter for new line) | ||
| * - Loading state management |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation claims features not implemented.
The JSDoc mentions "Auto-growing textarea" and "Submit on Enter (Shift+Enter for new line)", but the implementation uses a single-line <input type="text"> (line 104-106) which:
- Does not auto-grow
- Does not support multi-line input or Shift+Enter behavior
Either update the documentation to match the current implementation, or implement a textarea with the described features.
Proposed documentation fix
/**
* Chat input component - handles message input and submission
*
* Features:
- * - Auto-growing textarea
- * - Submit on Enter (Shift+Enter for new line)
+ * - Single-line text input
+ * - Submit on Enter (configurable via submitOnEnter prop)
* - Loading state management
* - Full render prop support for custom UIs📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| * Features: | |
| * - Auto-growing textarea | |
| * - Submit on Enter (Shift+Enter for new line) | |
| * - Loading state management | |
| /** | |
| * Chat input component - handles message input and submission | |
| * | |
| * Features: | |
| * - Single-line text input | |
| * - Submit on Enter (configurable via submitOnEnter prop) | |
| * - Loading state management | |
| * - Full render prop support for custom UIs | |
| */ |
| /** Callback when an error occurs */ | ||
| onError?: (error: Error) => void | ||
| /** Custom tool components registry */ | ||
| tools?: Record<string, any> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused tools prop declared but not passed to useChat.
The tools prop is defined in ChatProps but is not destructured in the Chat component nor passed to useChat. This appears to be dead code or an incomplete feature.
Proposed fix
Either remove the unused prop:
export interface ChatProps {
// ... other props
/** Callback when an error occurs */
onError?: (error: Error) => void
- /** Custom tool components registry */
- tools?: Record<string, any>
}Or pass it to useChat if it's a supported option:
export function Chat({
children,
className,
connection,
initialMessages,
id,
body,
onResponse,
onChunk,
onFinish,
onError,
+ tools,
}: ChatProps) {
const chat = useChat({
connection,
initialMessages,
id,
body,
onResponse,
onChunk,
onFinish,
onError,
+ tools,
})🤖 Prompt for AI Agents
In `@packages/typescript/ai-preact-ui/src/chat.tsx` at line 52, ChatProps declares
a tools?: Record<string, any> prop that the Chat component doesn't destructure
or forward to useChat, leaving dead code; either remove the tools field from
ChatProps and any related types/usages, or destructure tools in the Chat
component (e.g. function Chat({..., tools}: ChatProps)) and pass it into useChat
(e.g. useChat({ ..., tools })) so the prop is consumed—update tests/types
accordingly and ensure any runtime behavior expecting tools is preserved.
| const roleClassName = | ||
| role === 'user' | ||
| ? userClassName | ||
| : role === 'assistant' | ||
| ? assistantClassName | ||
| : '' | ||
| const combinedClassName = [className, roleClassName].filter(Boolean).join(' ') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation/implementation mismatch for system messages.
The JSDoc on line 15-16 states assistantClassName is "also used for system messages," but the implementation assigns an empty string to system role instead of assistantClassName.
Either update the implementation to match the docs:
Option 1: Apply assistantClassName to system role
const roleClassName =
role === 'user'
? userClassName
- : role === 'assistant'
- ? assistantClassName
- : ''
+ : role === 'assistant' || role === 'system'
+ ? assistantClassName
+ : ''Or update the JSDoc comment if the current behavior is intended.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const roleClassName = | |
| role === 'user' | |
| ? userClassName | |
| : role === 'assistant' | |
| ? assistantClassName | |
| : '' | |
| const combinedClassName = [className, roleClassName].filter(Boolean).join(' ') | |
| const roleClassName = | |
| role === 'user' | |
| ? userClassName | |
| : role === 'assistant' || role === 'system' | |
| ? assistantClassName | |
| : '' | |
| const combinedClassName = [className, roleClassName].filter(Boolean).join(' ') |
🤖 Prompt for AI Agents
In `@packages/typescript/ai-preact-ui/src/text-part.tsx` around lines 65 - 71, The
implementation currently sets roleClassName to '' for system messages causing a
mismatch with the JSDoc; change the conditional that computes roleClassName (the
role === 'user' ? userClassName : role === 'assistant' ? assistantClassName :
'') so that the fallback for the 'system' role uses assistantClassName (i.e.,
treat role === 'system' same as 'assistant'), or if the intended behavior is to
keep an empty class for system, update the JSDoc that describes
assistantClassName to remove the "also used for system messages" claim; adjust
either the roleClassName logic or the JSDoc accordingly so they match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/typescript/ai-preact-ui/README.md`:
- Line 12: The img tag has two alt attributes causing invalid HTML; remove the
duplicate empty alt and keep a single meaningful alt (e.g., alt="GitHub stars")
on the <img> element so it only has one alt attribute and conveys the intended
accessible text.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/typescript/ai-preact-ui/README.md
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Applied to files:
packages/typescript/ai-preact-ui/README.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Applied to files:
packages/typescript/ai-preact-ui/README.md
🪛 LanguageTool
packages/typescript/ai-preact-ui/README.md
[style] ~206-~206: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... rounded" /> ``` ### <ToolApproval> Renders approve/deny buttons for tools that req...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 markdownlint-cli2 (0.18.1)
packages/typescript/ai-preact-ui/README.md
2-2: Images should have alternate text (alt text)
(MD045, no-alt-text)
12-12: Hard tabs
Column: 1
(MD010, no-hard-tabs)
23-23: Hard tabs
Column: 1
(MD010, no-hard-tabs)
24-24: Hard tabs
Column: 1
(MD010, no-hard-tabs)
25-25: Hard tabs
Column: 1
(MD010, no-hard-tabs)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| <img alt="" src="https://img.shields.io/npm/dm/@tanstack/ai.svg" /> | ||
| </a> | ||
| <a href="https://github.com/TanStack/ai" target="\_parent"> | ||
| <img alt="" src="https://img.shields.io/github/stars/TanStack/ai.svg?style=social&label=Star" alt="GitHub stars" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix duplicate alt attribute.
The <img> tag contains two alt attributes (alt="" and alt="GitHub stars"), which is invalid HTML. Browsers typically use the first occurrence and ignore the second.
Proposed fix
- <img alt="" src="https://img.shields.io/github/stars/TanStack/ai.svg?style=social&label=Star" alt="GitHub stars" />
+ <img alt="GitHub stars" src="https://img.shields.io/github/stars/TanStack/ai.svg?style=social&label=Star" />📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <img alt="" src="https://img.shields.io/github/stars/TanStack/ai.svg?style=social&label=Star" alt="GitHub stars" /> | |
| <img alt="GitHub stars" src="https://img.shields.io/github/stars/TanStack/ai.svg?style=social&label=Star" /> |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
12-12: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In `@packages/typescript/ai-preact-ui/README.md` at line 12, The img tag has two
alt attributes causing invalid HTML; remove the duplicate empty alt and keep a
single meaningful alt (e.g., alt="GitHub stars") on the <img> element so it only
has one alt attribute and conveys the intended accessible text.
🎯 Changes
This adds the preact-ui package, we are using
preact-mdwhich I created mainly for this which already embeds the sanitize module.I need to figure out why the types of
unifiedhere aren't compatible. We do have a lighter variant ofpreact-markdownin/litebut this is more akin to the solid and react ones.Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.